#include <iostream>
#include <memory>
#include <cstdlib>
#include <unistd.h>
#include "Socket.hpp"
#include "Protocal.hpp"

using namespace Net_Work;

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        std::cout << "Usage:\n\t" << argv[0] << " serverip serverport" << std::endl;
    }
    std::string serverip = argv[1];
    uint16_t serverport = std::stoi(argv[2]);

    Net_Work::Socket *conn = new Net_Work::TcpSokcet;
    conn->BuildConnectSocketMethod(serverip, serverport);
    if (!conn->BuildConnectSocketMethod(serverip, serverport))
    {
        std::cerr << "connect " << serverip << ":" << serverport << " failed" << std::endl;
    }
    std::cout << "connect " << serverip << ":" << serverport << " success" << std::endl;

    srand(time(nullptr) ^ getpid());
    std::string opers = "+-%[]*/=";
    std::unique_ptr<Protocol::Factory> factory;
    while (true)
    {
        // 1.构建请求
        int x = rand() % 100;
        usleep(1000 * 100);
        int y = rand() % 100;
        char op = opers[rand() % opers.size()];
        std::shared_ptr<Protocol::Request> req = factory->BuildRequest(x, y, op);

        // 序列化
        std::string requeststr;
        req->Serialize(&requeststr);

        // for bebug
        std::string testreq = requeststr;
        testreq += " ";
        testreq += "= ";
        // 自描述报头字段
        requeststr = Protocol::Encode(requeststr);

        requeststr = Protocol::Encode(requeststr);

        // 发送请求
        conn->Send(requeststr);
        std::string responsestr;
        while (true)
        {
            // 读取响应
            if (!conn->Recv(&responsestr, 1024))
                break;
            // 报文进行解析
            std::string response;
            if (!Protocol::Decode(responsestr, &response))
                continue;
            auto resp = factory->BuildResponse();
            resp->Deserialize(response);
            // 结果
            std::cout << testreq << resp->GetResult() << "[" << resp->GetCode() << "]" << std::endl;
            break;
        }
        sleep(1);
    }
    return 0;
}